﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using EdytorWF.Objects;

namespace EdytorWF.Engine
{
    public class Environment
    {
        private Vector4 SunPosition;
        private Device MyDevice;
        private Effect MyEffect;
        private String TechniqueName;
        public Terrain MyTerrain { get; set; }
        public String EffectName = @"..\..\effects\MyEffect.fx";


        Texture Snow_Texture;
        Texture Ground_Texture;
        Texture Grass_Texture;
        Texture Rock_Texture;

        Matrix View;
        Matrix Projection;
        Vector3 Observer;

        //////////////////////////////////////////////////////////////////////////
        public Environment(Device dev)
        {
            MyDevice = dev;
            MyEffect = Effect.FromFile(MyDevice, @"..\..\effects\MyEffect.fx", null, ShaderFlags.None, null);

            Snow_Texture = TextureLoader.FromFile(MyDevice, @"..\..\Resources\Textures\snow.jpg");
            Ground_Texture = TextureLoader.FromFile(MyDevice, @"..\..\Resources\Textures\dirt.jpg");
            Grass_Texture = TextureLoader.FromFile(MyDevice, @"..\..\Resources\Textures\grass.jpg");
            Rock_Texture = TextureLoader.FromFile(MyDevice, @"..\..\Resources\Textures\rock.jpg");

            MyTerrain = new Terrain(dev);

            SunPosition = new Vector4
            {
                X = (float)r * (float)Math.Sin(Camera.ToRadians(b = b % 360)) * (float)Math.Cos(Camera.ToRadians(a = a % 360)),
                Y = (float)r * (float)Math.Cos(Camera.ToRadians(b = b % 360)),
                Z = (float)r * (float)Math.Sin(Camera.ToRadians(b = b % 360)) * (float)Math.Sin(Camera.ToRadians(a = a % 360)),
                W = 1.0f,
            };
        }

        //////////////////////////////////////////////////////////////////////////
        public void InitRenderOptions(Matrix view, Matrix projection, Vector3 observer)
        {
            View = view;
            Projection = projection;
            Observer = observer;
        }

        //////////////////////////////////////////////////////////////////////////
        public void RenderTerrain(String technique)
        {
            if (technique == null)
            {
                MyEffect.Technique = "terrain";
                TechniqueName = null;
            }
            else
            {
                MyEffect.Technique = technique;
                TechniqueName = technique;
            }

            MyEffect.SetValue("xWorld", Matrix.Identity);
            MyEffect.SetValue("xView", View);
            MyEffect.SetValue("xProjection", Projection);
            MyEffect.SetValue("xObserverPosition", new Vector4(Observer.X, Observer.Y, Observer.Z, 1.0f));

            MyEffect.SetValue("xLightPosition", SunPosition);
            MyEffect.SetValue("xTextureSnow", Snow_Texture);
            MyEffect.SetValue("xTextureGround", Ground_Texture);
            MyEffect.SetValue("xTextureGrass", Grass_Texture);
            MyEffect.SetValue("xTextureRock", Rock_Texture);
            MyEffect.SetValue("xMaxHeight", MyTerrain.MaxHeight);
            MyEffect.CommitChanges();

            int passes = MyEffect.Begin(0);
            for (int i = 0; i < passes; i++)
            {
                MyEffect.BeginPass(i);
                MyTerrain.Render();
                MyEffect.EndPass();
            }
            MyEffect.End();
        }

        //////////////////////////////////////////////////////////////////////////
        public void RenderTerrain(Effect effect, String technique)
        {
            if (effect == null)
            {
                RenderTerrain(technique);
                return;
            }

            int passes = effect.Begin(0);
            for (int i = 0; i < passes; i++)
            {
                effect.BeginPass(i);
                MyTerrain.Render();
                effect.EndPass();
            }
            effect.End();
        }
        //////////////////////////////////////////////////////////////////////////
        private float a = 1, b = 1, r = 100;

        public void MoveSun(float da, float db, float dr)
        {
            a += da;
            b += db;
            r += dr;

            Update();
        }

        //////////////////////////////////////////////////////////////////////////
        public void Update()
        {
            SunPosition = new Vector4
            {
                X = (float)r * (float)Math.Sin(Camera.ToRadians(b = b % 360)) * (float)Math.Cos(Camera.ToRadians(a = a % 360)),
                Y = (float)r * (float)Math.Cos(Camera.ToRadians(b = b % 360)),
                Z = (float)r * (float)Math.Sin(Camera.ToRadians(b = b % 360)) * (float)Math.Sin(Camera.ToRadians(a = a % 360)),
                W = 1.0f,
            };
            RenderTerrain(TechniqueName);
        }

        //////////////////////////////////////////////////////////////////////////
    }
}
